#include "Mystring.h"
#include <ios>
#include <stdexcept>
#include <string.h>

// 默认构造函数
MySTL::Mystring::Mystring() : m_len(0), m_cap(0) {
  m_data_ = new char[1];
  m_data_[0] = '\0';
};
// 从c风格字符串创建
MySTL::Mystring::Mystring(const char *cstr) {
  size_t len = strlen(cstr);
  m_data_ = new char[len + 1];
  m_cap = len;
  m_len = len;
  memcpy(m_data_, cstr, len);
  m_data_[len] = '\0';
}
// 拷贝构造函数
MySTL::Mystring::Mystring(const Mystring &other) {
  m_data_ = new char[other.m_len + 1];
  memcpy(m_data_, other.m_data_, other.m_len);
  m_data_[other.m_len] = '\0';
  m_len = other.m_len;
  m_cap = other.m_len;
}
// 移动拷贝构造函数
MySTL::Mystring::Mystring(Mystring &&other) {
  m_data_ = other.m_data_;
  m_len = other.m_len;
  m_cap = other.m_cap;
  other.m_data_ = nullptr;
  other.m_len = 0;
  other.m_cap = 0;
}

// 析构函数
MySTL::Mystring::~Mystring() {
  if (m_data_) {
    delete[] m_data_;
    m_len = 0;
    m_cap = 0;
  }
};

// 赋值运算符重载
MySTL::Mystring &MySTL::Mystring::operator=(const char *cstr) {
  size_t len = strlen(cstr);
  if (len > (m_cap - 1)) {
    delete[] m_data_;
    m_data_ = new char[len + 1];
    m_cap = len;
  }
  memcpy(m_data_, cstr, len);
  m_data_[len] = '\0';
  m_len = len;
  return *this;
}

MySTL::Mystring &MySTL::Mystring::operator=(const Mystring &other) {
  if (this == &other)
    return *this;
  if (m_cap >= other.m_len) {
    std::memcpy(m_data_, other.m_data_, other.m_len);
    m_len = other.m_len;
  } else {
    delete[] m_data_;
    m_data_ = new char[other.m_len + 1];
    memcpy(m_data_, other.m_data_, other.m_len);
    m_len = other.m_len;
    m_cap = m_len;
    m_data_[m_len] = '\0';
  }
  return *this;
}

MySTL::Mystring &MySTL::Mystring::operator=(Mystring &&other) {
  if (this == &other)
    return *this;
  if (m_data_) {
    delete[] m_data_;
  }
  m_data_ = other.m_data_;
  m_len = other.m_len;
  m_cap = other.m_cap;
  other.m_data_ = nullptr;
  other.m_len = 0;
  other.m_cap = 0;
  return *this;
}

size_t MySTL::Mystring::size() const { return m_len; }

size_t MySTL::Mystring::length() const { return m_len; }

size_t MySTL::Mystring::capacity() const { return m_cap; }

char &MySTL::Mystring::operator[](size_t pos) { return m_data_[pos]; }

const char &MySTL::Mystring::operator[](size_t pos) const {
  return m_data_[pos];
}

char &MySTL::Mystring::at(size_t pos) {
  if (pos >= m_len) {
    throw std::out_of_range("pos out of bounds");
  }
  return m_data_[pos];
}

const char &MySTL::Mystring::at(size_t pos) const { return this->at(pos); }

void MySTL::Mystring::clear() {
  m_len = 0;
  m_data_[0] = 0;
}

bool MySTL::Mystring::empty() const { return m_len == 0; }

void MySTL::Mystring::resize(size_t n, char c) {
  // 超出最大容量: 扩容
  if (n > m_cap) {
    while (n > m_cap) {
      m_cap = (m_cap == 0) ? 1 : 2 * m_cap;
    }
    char *data_t = new char[m_cap + 1];
    if (m_len > 0) {
      memcpy(data_t, m_data_, m_len);
    }
    delete[] m_data_;
    m_data_ = data_t;
  }
  if (m_len == 0) {
    for (size_t i = 0; i < n; ++i) {
      m_data_[i] = c;
    }
  } else {
    if (m_len < n) {
      for (size_t i = m_len; i < n; ++i) {
        m_data_[i] = c;
      }
    }
  }
  m_data_[n] = '\0';
  m_len = n;
}

const char *MySTL::Mystring::c_str() const { return m_data_; }

MySTL::Mystring &MySTL::Mystring::operator+=(const char *cstr) {
  size_t len = strlen(cstr);
  if (m_len + len > m_cap) {
    while (m_len + len > m_cap) {
      // 初始容量为0时，从1开始计算合适容量
      m_cap = (m_cap == 0) ? 1 : 2 * m_cap;
    }
    char *data_t = new char[m_cap + 1];
    memcpy(data_t, m_data_, m_len);
    delete[] m_data_;
    m_data_ = data_t;
  }
  memcpy(m_data_ + m_len, cstr, len);
  m_data_[m_len + len] = '\0';
  m_len += len;
  return *this;
}

MySTL::Mystring &MySTL::Mystring::operator+=(const Mystring &str) {
  if (m_len + str.m_len > m_cap) {
    while (m_len + str.m_len > m_cap) {
      m_cap = (m_cap == 0) ? 1 : 2 * m_cap;
    }
    char *data_t = new char[m_cap + 1];
    memcpy(data_t, m_data_, m_len);
    delete[] m_data_;
    m_data_ = data_t;
  }
  memcpy(m_data_ + m_len, str.m_data_, str.m_len);
  m_data_[m_len + str.m_len] = '\0';
  m_len += str.m_len;
  return *this;
}

MySTL::Mystring &MySTL::Mystring::operator+=(char c) {
  if (m_len + 1 > m_cap) {
    m_cap = m_cap == 0 ? 1 : m_cap * 2;
    char *data_t = new char[m_cap + 1];
    memcpy(data_t, m_data_, m_len);
    delete[] m_data_;
    m_data_ = data_t;
  }
  m_data_[m_len] = c;
  m_len += 1;
  m_data_[m_len] = '\0';
  return *this;
}

void MySTL::Mystring::push_back(char ch) { operator+=(ch); }

MySTL::Mystring &MySTL::Mystring::append(const char *cstr) {
  return operator+=(cstr);
}

MySTL::Mystring &MySTL::Mystring::append(const char *cstr, size_t len) {
  if (m_cap - m_len < len) {
    // 剩余空间不足 扩容
    while (m_cap - m_len < len) {
      m_cap = (m_cap == 0) ? 1 : 2 * m_cap;
    }
    char *data_t = new char[m_cap + 1];
    memcpy(data_t, m_data_, m_len);
    delete[] m_data_;
    m_data_ = data_t;
  }
  memcpy(m_data_ + m_len, cstr, len);
  m_len += len;
  m_data_[m_len] = '\0';
  return *this;
}

MySTL::Mystring &MySTL::Mystring::append(const Mystring &other) {
  return operator+=(other);
}

MySTL::Mystring MySTL::Mystring::substr(size_t pos, size_t len) const {
  if (pos >= m_len) {
    throw std::out_of_range("pos out of bounds");
  }
  if (len == 0) {
    return Mystring();
  }
  if (pos + len >= m_len) {
    return MySTL::Mystring(m_data_ + pos);
  } else {
    char *buf = new char[len + 1];
    memcpy(buf, m_data_ + pos, len);
    buf[len] = '\0';
    Mystring str(buf);
    delete[] buf;
    return str;
  }
}

bool MySTL::Mystring::operator==(const Mystring &other) const {
  if (m_len != other.m_len)
    return false;
  if (this == &other)
    return true;
  for (size_t i = 0; i < m_len; i++) {
    if (m_data_[i] != other.m_data_[i]) {
      return false;
    }
  }
  return true;
}

bool MySTL::Mystring::operator!=(const Mystring &other) const {
  if (m_len != other.m_len)
    return true;
  if (this == &other)
    return false;
  for (size_t i = 0; i < m_len; ++i) {
    if (m_data_[i] != other.m_data_[i]) {
      return true;
    }
  }
  return false;
}

bool MySTL::Mystring::operator<(const Mystring &other) const {
  size_t minLen = std::min(m_len, other.m_len);
  for (size_t i = 0; i < minLen; ++i) {
    if (m_data_[i] >= other.m_data_[i]) {
      return false;
    }
  }
  if (m_len < other.m_len) {
    return true;
  }
  return false;
}

bool MySTL::Mystring::operator>(const Mystring &other) const {
  size_t minLen = std::min(m_len, other.m_len);
  for (size_t i = 0; i < minLen; ++i) {
    if (m_data_[i] <= other.m_data_[i]) {
      return false;
    }
  }
  if (m_len > other.m_len) {
    return true;
  }
  return false;
}

bool MySTL::Mystring::operator<=(const Mystring &other) const {
  size_t minLen = std::min(m_len, other.m_len);
  for (size_t i = 0; i < minLen; ++i) {
    if (m_data_[i] > other.m_data_[i]) {
      return false;
    }
  }
  if (m_len <= other.m_len) {
    return true;
  }
  return false;
}

bool MySTL::Mystring::operator>=(const Mystring &other) const {
  size_t minLen = std::min(m_len, other.m_len);
  for (size_t i = 0; i < minLen; ++i) {
    if (m_data_[i] < other.m_data_[i]) {
      return false;
    }
  }
  if (m_len >= other.m_len) {
    return true;
  }
  return false;
}

std::ostream &operator<<(std::ostream &os, const MySTL::Mystring &str) {
  os << str.c_str();
  return os;
}

std::istream &operator>>(std::istream &is, MySTL::Mystring &str) {
  str.clear();
  char buf[1024];
  memset(buf, 0, 1024);
  while (is.read(buf, 1024)) {
    str.append(buf, sizeof(buf));
  }
  std::streamsize remaining = is.gcount();
  if (remaining > 0) {
    str.append(buf, remaining);
  }
  return is;
}
